package com.guazai.project.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.guazai.common.pojo.User;
import com.guazai.project.annotation.AuthCheck;
import com.guazai.project.common.BaseResponse;
import com.guazai.project.common.DeleteRequest;
import com.guazai.project.common.ErrorCode;
import com.guazai.project.common.ResultUtils;
import com.guazai.project.constant.CommonConstant;
import com.guazai.project.constant.UserConstant;
import com.guazai.project.exception.BusinessException;
import com.guazai.project.model.dto.user.*;
import com.guazai.project.model.vo.LoginUserVO;
import com.guazai.project.model.vo.UserVO;
import com.guazai.project.model.vo.UserVoucherVO;
import com.guazai.project.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

import static com.guazai.project.constant.UserConstant.DEFAULT_USER_AVATAR;

/**
 * 用户接口
 *
 * @author guazai
 */
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    /**
     * 主机地址
     */
    @Value("${guazai-api.host}")
    private String apiHost;

    @Resource
    private UserService userService;

    @Value("${guazai-api.defaultPassWord}")
    private String defaultPassWord;

    /**
     * 用户注册
     *
     * @param userRegisterRequest
     * @return
     */
    @PostMapping("/register")
    public BaseResponse<Long> userRegister(@RequestBody UserRegisterRequest userRegisterRequest) {
        //参数校验
        if (userRegisterRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        String userAccount = userRegisterRequest.getUserAccount();
        String userPassword = userRegisterRequest.getUserPassword();
        String checkPassword = userRegisterRequest.getCheckPassword();
        if (StringUtils.isAnyBlank(userAccount, userPassword, checkPassword)) {
            return null;
        }
        //调用业务层的注册方法
        long result = userService.userRegister(userAccount, userPassword, checkPassword);
        //返回结果
        return ResultUtils.success(result);
    }

    /**
     * 用户登录
     *
     * @param userLoginRequest
     * @param request
     * @return
     */
    @PostMapping("/login")
    public BaseResponse<User> userLogin(@RequestBody UserLoginRequest userLoginRequest, HttpServletRequest request) {
        // 参数校验
        if (userLoginRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        String userAccount = userLoginRequest.getUserAccount();
        String userPassword = userLoginRequest.getUserPassword();
        if (StringUtils.isAnyBlank(userAccount, userPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 调用业务层的登录方法
        User user = userService.userLogin(userAccount, userPassword, request);
        // 返回结果
        return ResultUtils.success(user);
    }

    /**
     * 用户注销
     *
     * @param request
     * @return
     */
    @PostMapping("/logout")
    public BaseResponse<Boolean> userLogout(HttpServletRequest request) {
        // 参数校验
        if (request == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 调用业务层的注销方法
        boolean result = userService.userLogout(request);
        return ResultUtils.success(result);
    }

    /**
     * 获取当前登录用户
     *
     * @param request
     * @return
     */
    @GetMapping("/get/login")
    public BaseResponse<UserVO> getLoginUser(HttpServletRequest request) {
        // 调用业务层的getLogin方法
        User user = userService.getLoginUser(request);
        // 将user转化成userVO
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        // 返回结果
        return ResultUtils.success(userVO);
    }

    /**
     * 创建用户
     *
     * @param userAddRequest
     * @param request
     * @return
     */
    @PostMapping("/add")
    public BaseResponse<Long> addUser(@RequestBody UserAddRequest userAddRequest, HttpServletRequest request) {
        // 参数校验
        if (userAddRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 将参数封装成User对象
        User user = new User();
        BeanUtils.copyProperties(userAddRequest, user);
        user.setUserPassword(defaultPassWord);
        user.setUserAvatar(apiHost + DEFAULT_USER_AVATAR);
        Long resultId = userService.addUser(user);
        // 通过id判断是否添加成功
        if (resultId == null) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR);
        }
        // 返回id
        return ResultUtils.success(resultId);
    }

    /**
     * 删除用户
     *
     * @param deleteRequest
     * @param request
     * @return
     */
    @PostMapping("/deleteById")
    public BaseResponse<Boolean> deleteUser(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) {
        // 参数校验
        if (deleteRequest == null || deleteRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 调用业务层的removeUser方法
        boolean b = userService.removeUser(deleteRequest);
        // 返回结果
        return ResultUtils.success(b);
    }

    /**
     * 更新用户
     *
     * @param userUpdateRequest
     * @return
     */
    @PostMapping("/update")
    public BaseResponse<Boolean> updateUser(@RequestBody UserUpdateRequest userUpdateRequest) {
        // 参数校验
        log.info("开始修改用户，用户参数为：{}", userUpdateRequest);
        Long id = userUpdateRequest.getId();
        if (userUpdateRequest == null || id == null || id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 调用业务层的updateUser方法
        boolean result = userService.updateUser(userUpdateRequest);
        // 返回结果
        return ResultUtils.success(result);
    }

    /**
     * 根据 id 获取用户
     *
     * @param id
     * @return
     */
    @GetMapping("/get")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<User> getUserById(long id) {
        //参数校验
        if (id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 调用业务层的getById方法
        User user = userService.getById(id);
        // 返回结果
        return ResultUtils.success(user);
    }

    /**
     * 获取用户列表
     *
     * @param userQueryRequest
     * @return
     */
    @GetMapping("/list")
    public BaseResponse<List<UserVO>> listUser(UserQueryRequest userQueryRequest) {
        // 参数复制
        User userQuery = new User();
        if (userQueryRequest != null) {
            //参数不为空则将userQueryRequest的属性复制到userQuery中
            BeanUtils.copyProperties(userQueryRequest, userQuery);
        }
        // 查询条件queryWrapper封装
        QueryWrapper<User> queryWrapper = new QueryWrapper<>(userQuery);
        // 调用业务层的list方法查询
        List<User> userList = userService.list(queryWrapper);
        // 通过Stream流将User映射成UserVO
        List<UserVO> userVOList = userList.stream().map(user -> {
            UserVO userVO = new UserVO();
            BeanUtils.copyProperties(user, userVO);
            return userVO;
        }).collect(Collectors.toList());
        // 返回查询结果
        return ResultUtils.success(userVOList);
    }

    /**
     * 分页获取用户列表
     *
     * @param userQueryRequest
     * @return
     */
    @GetMapping("/list/page")
    public BaseResponse<Page<UserVO>> listUserByPage(UserQueryRequest userQueryRequest) {
        //如果参数为空，则设置默认分页查询参数
        long current = CommonConstant.DEFAULT_PAGEQUERY_CURRENT;
        long size = CommonConstant.DEFAULT_PAGEQUERY_PAGESIZE;
        User userQuery = new User();
        // 如果参数不为空，则将userQueryRequest复制到userQuery中
        if (userQueryRequest != null) {
            BeanUtils.copyProperties(userQueryRequest, userQuery);
            current = userQueryRequest.getCurrent();
            size = userQueryRequest.getPageSize();
        }
        // 调用业务层方法查询
        QueryWrapper<User> queryWrapper = new QueryWrapper<>(userQuery);
        Page<User> userPage = userService.page(new Page<>(current, size), queryWrapper);
        // 将User转为UserVO类型
        List<UserVO> userVOList = userPage.getRecords().stream().map(user -> {
            UserVO userVO = new UserVO();
            BeanUtils.copyProperties(user, userVO);
            return userVO;
        }).collect(Collectors.toList());
        // 创建UserVOPage对象
        Page<UserVO> userVOPage = new PageDTO<>(userPage.getCurrent(), userPage.getSize(), userPage.getTotal());
        userVOPage.setRecords(userVOList);
        return ResultUtils.success(userVOPage);
    }

    @PostMapping("/list/page/vo")
    public BaseResponse<Page<UserVO>> listUserVOByPage(@RequestBody UserQueryRequest userQueryRequest) {
        // 参数校验
        if (userQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 调用业务层的listUserVOByPage方法
        Page<UserVO> userVOPage = userService.listUserVOByPage(userQueryRequest);
        // 返回结果
        return ResultUtils.success(userVOPage);
    }

    /**
     * 获取凭证
     * @param request
     * @return
     */
    @GetMapping("/get/voucher")
    public BaseResponse<UserVoucherVO> getVoucher(HttpServletRequest request) {
        // 调用业务层的getVoucher方法
        User user = userService.getVoucher(request);
        UserVoucherVO userVoucherVO = BeanUtil.copyProperties(user, UserVoucherVO.class);
        //返回结果
        return ResultUtils.success(userVoucherVO);
    }

    /**
     * 删除用户（多个id）
     *
     * @param deleteListRequest
     * @param request
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/deleteByIds")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Boolean> deleteUserByIds(@RequestBody DeleteListRequest deleteListRequest, HttpServletRequest request) {
        boolean removeByIdsFlag = userService.deleteUserByIds(deleteListRequest, request);
        if (!removeByIdsFlag) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "数据库删除异常");
        }
        return ResultUtils.success(removeByIdsFlag);
    }

    /**
     * 更新个人信息
     * @param userUpdateMyRequest
     * @param request
     * @return
     */
    @PostMapping("/update/my")
    public BaseResponse<Boolean> updateMyUser(@RequestBody UserUpdateMyRequest userUpdateMyRequest,
                                              HttpServletRequest request) {
        if (userUpdateMyRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        User user = new User();
        BeanUtils.copyProperties(userUpdateMyRequest, user);
        user.setId(loginUser.getId());
        boolean result = userService.updateById(user);
        if (!result) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR);
        }
        return ResultUtils.success(true);
    }

    /**
     * 根据 id 获取UserVO
     *
     * @param id
     * @return
     */
    @GetMapping("/get/vo")
    public BaseResponse<UserVO> getUserVOById(long id) {
        if (id < 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "id小于0");
        }

        User user = userService.getById(id);
        //数据库中无对应数据
        if (user == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "不存在该用户");
        }

        UserVO userVO = userService.getUserVO(user);
        return ResultUtils.success(userVO);
    }

    /**
     * 修改用户密码
     * @param userUpdatePasswordRequest
     * @param request
     * @return
     */
    @PostMapping("/update/password")
    public BaseResponse<Boolean> updatePassword(@RequestBody UserUpdatePasswordRequest userUpdatePasswordRequest, HttpServletRequest request) {
        if (ObjUtil.isEmpty(userUpdatePasswordRequest)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User loginUser = userService.getLoginUser(request);
        // 是否登录
        if(ObjUtil.isEmpty(loginUser)){
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        return ResultUtils.success(userService.updatePassword(userUpdatePasswordRequest,loginUser.getId()));
    }

    /**
     * 修改用户名
     * @param userNameUpdateRequest
     * @return
     */
    @PostMapping("/update/username")
    public BaseResponse<Boolean> updateUserName(@RequestBody UserNameUpdateRequest userNameUpdateRequest) {
        User user = new User();
        user.setId(userNameUpdateRequest.getId());
        user.setUserName(userNameUpdateRequest.getUserName());
        boolean updateFlag = userService.updateUserName(user);
        if(!updateFlag){
            throw new BusinessException(ErrorCode.OPERATION_ERROR);
        }
        return ResultUtils.success(true);
    }

    /**
     * 登录发送短信验证码
     *
     * @param userLoginByEmailRequest
     * @param request
     * @return
     */
    @PostMapping("/login/email/sendVerificationCode")
    public BaseResponse<Boolean> loginSendVerificationCode(@RequestBody UserLoginByEmailRequest userLoginByEmailRequest, HttpServletRequest request) {
        if (userLoginByEmailRequest == null || request == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        String to = userLoginByEmailRequest.getEmail();
        if (StringUtils.isBlank(to)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "邮箱为空");
        }

        return ResultUtils.success(userService.sendCodeEmail(to, request));
    }

    /**
     * 邮箱登录
     * @param userLoginByEmailRequest
     * @param request
     * @return
     */
    @PostMapping("/login/email")
    public BaseResponse<LoginUserVO> userLoginByEmail(@RequestBody UserLoginByEmailRequest userLoginByEmailRequest, HttpServletRequest request) {
        if (userLoginByEmailRequest == null) {
            return ResultUtils.error(ErrorCode.PARAMS_ERROR);
        }
        return ResultUtils.success(userService.userLoginByEmail(userLoginByEmailRequest, request));
    }

    @PostMapping("/email/sendVerificationCode")
    public BaseResponse<Boolean> sendVerificationCode(@RequestBody UserSendEmailRequest userSendEmailRequest, HttpServletRequest request) {
        String to = userSendEmailRequest.getEmail();
        // 发送验证码
        return ResultUtils.success(userService.sendCodeEmail(to, request));
    }

    /**
     * 绑定邮箱
     * @param userBindEmailRequest
     * @param request
     * @return
     */
    @PostMapping("/email/bind")
    public BaseResponse<Boolean> bindEmail(@RequestBody UserBindEmailRequest userBindEmailRequest, HttpServletRequest request) {
        if (userBindEmailRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        return ResultUtils.success(userService.bindEmail(userBindEmailRequest, request));
    }

    /**
     * 解绑邮箱
     * @param request
     * @return
     */
    @PostMapping("/email/unbind")
    public BaseResponse<Boolean> unbindEmail(HttpServletRequest request) {
        return ResultUtils.success(userService.unBindEmail(request));
    }

    /**
     * 更新秘钥
     * @param request
     * @return
     */
    @PostMapping("/update/voucher")
    public BaseResponse<UserVoucherVO> updateVoucher(HttpServletRequest request) {
        UserVoucherVO userVoucherVO =  userService.updateVoucher(request);
        return ResultUtils.success(userVoucherVO);
    }
}
